package gui;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.DefaultComboBoxModel;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;

import matrix.GaussElim;
import matrix.GaussElimPiv;
import matrix.GaussSeidel;
import matrix.Jacobi;
import matrix.LUDecomp;
import matrix.Matrix;
import matrix.SSLE;
import matrix.Utils;

import org.scilab.forge.jlatexmath.TeXConstants;
import org.scilab.forge.jlatexmath.TeXFormula;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;

public class InputPanel extends JPanel {
	private static final long serialVersionUID = -6466208725521990942L;
	
	public JPanel pnlTitle;
	public JScrollPane scrl;
	public JTable table;
	public JButton btnSize;
	public JPanel pnlSol;
	public JComboBox<String> comboBox;
	public JPanel panel;
	public JComboBox<SSLE> comboBox_1;
	public JButton btnSolve;
	public JButton btnSteps;
	
	private JSpinner spinner;
	
	public static void main(String[] args) throws Exception {
		UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		JFrame f = new JFrame();
		InputPanel d = new InputPanel();
		f.setContentPane(d);
		f.setVisible(true);
		f.pack();
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	public InputPanel() {
		init();
	}
	
	private void init() {
		setFocusable(false);
		setSize(new Dimension(256, 281));
		
		pnlTitle = new JPanel() {
			private static final long serialVersionUID = -839438457353149313L;
			
			@Override
			public void paint(Graphics g) {
				super.paint(g);
				new TeXFormula("[A|B] =").createTeXIcon(TeXConstants.STYLE_DISPLAY, 14).paintIcon(this, g, 4, 4);
			}
		};
		pnlTitle.setFocusable(false);
		pnlTitle.setBorder(UIManager.getBorder("FileChooser.listViewBorder"));
		
		scrl = new JScrollPane();
		
		btnSize = new JButton("Size");
		btnSize.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent paramActionEvent) {
				do_btnSize_actionPerformed(paramActionEvent);
			}
		});
		
		pnlSol = new JPanel() {
			private static final long serialVersionUID = -839438457353149313L;
			
			@Override
			public void paint(Graphics g) {
				super.paint(g);
				new TeXFormula("Solve").createTeXIcon(TeXConstants.STYLE_DISPLAY, 14).paintIcon(this, g, 4, 4);
			}
		};
		pnlSol.setFocusable(false);
		pnlSol.setBorder(UIManager.getBorder("FileChooser.listViewBorder"));
		GroupLayout gl_panel = new GroupLayout(pnlSol);
		gl_panel.setHorizontalGroup(gl_panel.createParallelGroup(Alignment.LEADING).addGap(0, 256, Short.MAX_VALUE).addGap(0, 256, Short.MAX_VALUE));
		gl_panel.setVerticalGroup(gl_panel.createParallelGroup(Alignment.LEADING).addGap(0, 24, Short.MAX_VALUE).addGap(0, 24, Short.MAX_VALUE));
		pnlSol.setLayout(gl_panel);
		
		comboBox = new JComboBox<String>();
		comboBox.setModel(new DefaultComboBoxModel<String>(new String[] { "Integer", "Float", "Double" }));
		comboBox.setSelectedIndex(2);
		
		panel = new JPanel() {
			private static final long serialVersionUID = -839438457353149313L;
			
			@Override
			public void paint(Graphics g) {
				super.paint(g);
				new TeXFormula("Method").createTeXIcon(TeXConstants.STYLE_DISPLAY, 14).paintIcon(this, g, 4, 4);
			}
		};
		panel.setFocusable(false);
		
		comboBox_1 = new JComboBox<SSLE>();
		comboBox_1.setModel(new DefaultComboBoxModel<SSLE>(new SSLE[] { new GaussElim(), new GaussElimPiv(), new LUDecomp(), new Jacobi(), new GaussSeidel() }));
		
		btnSolve = new JButton("Solve");
		
		btnSteps = new JButton("Steps");
		
		spinner = new JSpinner();
		spinner.setModel(new SpinnerNumberModel(new Integer(10), new Integer(1), null, new Integer(1)));
		
		GroupLayout groupLayout = new GroupLayout(this);
		groupLayout.setHorizontalGroup(groupLayout
				.createParallelGroup(Alignment.TRAILING)
				.addGroup(
						Alignment.LEADING,
						groupLayout.createSequentialGroup().addGap(6).addComponent(btnSize).addPreferredGap(ComponentPlacement.RELATED)
								.addComponent(comboBox, GroupLayout.PREFERRED_SIZE, 93, GroupLayout.PREFERRED_SIZE).addPreferredGap(ComponentPlacement.RELATED)
								.addComponent(spinner, GroupLayout.DEFAULT_SIZE, 84, Short.MAX_VALUE).addContainerGap())
				.addComponent(scrl, GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE)
				.addComponent(pnlTitle, GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE)
				.addComponent(pnlSol, GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE)
				.addGroup(
						groupLayout.createSequentialGroup().addContainerGap().addComponent(panel, GroupLayout.PREFERRED_SIZE, 64, GroupLayout.PREFERRED_SIZE)
								.addPreferredGap(ComponentPlacement.RELATED).addComponent(comboBox_1, 0, 166, Short.MAX_VALUE).addContainerGap())
				.addGroup(
						groupLayout.createSequentialGroup().addContainerGap(122, Short.MAX_VALUE).addComponent(btnSteps).addPreferredGap(ComponentPlacement.RELATED)
								.addComponent(btnSolve).addContainerGap()));
		groupLayout.setVerticalGroup(groupLayout.createParallelGroup(Alignment.LEADING).addGroup(
				groupLayout
						.createSequentialGroup()
						.addComponent(pnlTitle, GroupLayout.PREFERRED_SIZE, 24, GroupLayout.PREFERRED_SIZE)
						.addPreferredGap(ComponentPlacement.RELATED)
						.addComponent(scrl, GroupLayout.DEFAULT_SIZE, 127, Short.MAX_VALUE)
						.addPreferredGap(ComponentPlacement.RELATED)
						.addGroup(
								groupLayout.createParallelGroup(Alignment.BASELINE).addComponent(btnSize)
										.addComponent(comboBox, GroupLayout.PREFERRED_SIZE, 24, GroupLayout.PREFERRED_SIZE)
										.addComponent(spinner, GroupLayout.PREFERRED_SIZE, 20, GroupLayout.PREFERRED_SIZE))
						.addPreferredGap(ComponentPlacement.RELATED)
						.addComponent(pnlSol, GroupLayout.PREFERRED_SIZE, 24, GroupLayout.PREFERRED_SIZE)
						.addPreferredGap(ComponentPlacement.RELATED)
						.addGroup(
								groupLayout.createParallelGroup(Alignment.LEADING).addComponent(panel, GroupLayout.PREFERRED_SIZE, 21, GroupLayout.PREFERRED_SIZE)
										.addComponent(comboBox_1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
						.addPreferredGap(ComponentPlacement.RELATED)
						.addGroup(groupLayout.createParallelGroup(Alignment.BASELINE).addComponent(btnSolve).addComponent(btnSteps)).addGap(9)));
		GroupLayout gl_panel1 = new GroupLayout(panel);
		gl_panel1.setHorizontalGroup(gl_panel1.createParallelGroup(Alignment.LEADING).addGap(0, 76, Short.MAX_VALUE));
		gl_panel1.setVerticalGroup(gl_panel1.createParallelGroup(Alignment.LEADING).addGap(0, 21, Short.MAX_VALUE));
		panel.setLayout(gl_panel1);
		
		table = new JTable();
		setMatrixSize(3);
		table.setCellSelectionEnabled(true);
		scrl.setViewportView(table);
		GroupLayout gl_panel11 = new GroupLayout(pnlTitle);
		gl_panel11.setHorizontalGroup(gl_panel11.createParallelGroup(Alignment.LEADING).addGap(0, 215, Short.MAX_VALUE));
		gl_panel11.setVerticalGroup(gl_panel11.createParallelGroup(Alignment.LEADING).addGap(0, 45, Short.MAX_VALUE));
		pnlTitle.setLayout(gl_panel11);
		setLayout(groupLayout);
	}
	
	public void setMatrixSize(int size) {
		String[] h = new String[size + 1];
		for (int i = 0; i < h.length - 1; i++)
			h[i] = "A" + (i + 1);
		h[h.length - 1] = "B1";
		table.setModel(new DefaultTableModel(h, size));
		for (int i = 0; i < h.length; i++) {
			table.getColumnModel().getColumn(i).setResizable(false);
			table.getColumnModel().getColumn(i).setMinWidth(48);
		}
	}
	
	protected void do_btnSize_actionPerformed(ActionEvent paramActionEvent) {
		int old = table.getModel().getRowCount();
		try {
			setMatrixSize(Integer.parseInt(JOptionPane.showInputDialog(this, "Insert matrix dimension", "")));
		} catch (Exception e) {
			setMatrixSize(old);
		}
	}
	
	public Matrix getMatrixA() {
		String[][] s = new String[table.getModel().getRowCount()][table.getModel().getColumnCount() - 1];
		for (int i = 0; i < s.length; i++)
			for (int j = 0; j < s[i].length; j++)
				s[i][j] = (String) table.getValueAt(i, j);
		return new Matrix(s, Utils.get((String) comboBox.getSelectedItem()));
	}
	
	public Matrix getMatrixB() {
		String[][] s = new String[table.getModel().getRowCount()][1];
		for (int i = 0; i < s.length; i++)
			s[i][0] = (String) table.getValueAt(i, table.getModel().getColumnCount() - 1);
		return new Matrix(s, Utils.get((String) comboBox.getSelectedItem()));
	}
	
	public int getIterations() {
		return (Integer) spinner.getValue();
	}
	
	public void setTable(ArrayList<ArrayList<Double>> lst2d) {
		setMatrixSize(lst2d.size());
		for (int i = 0; i < lst2d.size(); i++)
			for (int j = 0; j < lst2d.get(0).size(); j++)
				table.setValueAt(lst2d.get(i).get(j) + "", i, j);
	}
}
